﻿using EmailClient.Model;
using EmailClient.ViewModel;
using LumiSoft.Net.Log;
using LumiSoft.Net.Mail;
using LumiSoft.Net.POP3.Client;
using LumiSoft.Net.SMTP.Client;
using ServiceStack.OrmLite;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;


namespace EmailClient.Mail
{
    public class POP3
    {
        public static void CreateUpdateFolders(EmailAccount item)
        {
            var dbFactory = new OrmLiteConnectionFactory(App.DBPath, SqliteDialect.Provider, false);
            using (var db = dbFactory.Open())
            {
                int countFolders = (int)db.Count<MailFolder>(x => x.AccountId == item.Id);
                if (countFolders == 0)
                {
                    db.Insert(new MailFolder { Name = "Входящие", AccountId = item.Id, StatusId = 0 });
                    db.Insert(new MailFolder { Name = "Отправленные", AccountId = item.Id, StatusId = 1 });
                    db.Insert(new MailFolder { Name = "Черновики", AccountId = item.Id, StatusId = 2 });
                    db.Insert(new MailFolder { Name = "Спам", AccountId = item.Id, StatusId = 3 });
                    db.Insert(new MailFolder { Name = "Корзина", AccountId = item.Id, StatusId = 4 });
                }
            }              
        }

        public static string CheckData(EmailAccount account)
        {
            var result = "success";
            using (var pop3 = new POP3_Client())
            {
                try
                {
                    pop3.Connect(account.inServer.Trim(), Convert.ToInt16(account.inPort), account.UseSSL);
                    pop3.Login(account.UserName.Trim(), account.Password);
                }
                catch (Exception e)
                {
                   return "POP3 server returned: " + e.Message;
                }
            }
            return result;
        }

        public static async Task<string> GetLetters(EmailAccount account)
        {
            var result = "success";
            using (POP3_Client pop3 = new POP3_Client())
            {
                try
                {
                    pop3.Connect(account.inServer.Trim(), Convert.ToInt16(account.inPort), account.UseSSL);
                    pop3.Login(account.UserName.Trim(), account.Password);

                    foreach (POP3_ClientMessage message in pop3.Messages)
                    {
                        Mail_Message mime = Mail_Message.ParseFromByte(message.MessageToByte());
                        await ProcessMessage(mime, account);
                    }
                }
                catch (Exception e)
                {
                    result = "POP3 server returned: " + e.Message;
                }
            }
            return result;
        }

        private static async Task<string> ProcessMessage(Mail_Message email, EmailAccount account)
        {
            var result = "success";
            try
            {
                var newEmail = new Letter();
                newEmail.Bcc = (email.Bcc == null ? null : email.Bcc.ToString());
                newEmail.BodyAsText = email.BodyText;
                newEmail.BodyAsHTML = email.BodyHtmlText;
                newEmail.CC = (email.Cc == null ? null : email.Cc.ToString());
                newEmail.DepartureDate = (DateTime)email.Date;
                newEmail.FromSent = email.From.ToString();
                newEmail.MessageId = email.MessageID;
                newEmail.Subject = email.Subject;
                newEmail.ToSent = email.To.ToString();
                newEmail.AccountId = account.Id;
                newEmail.Account = account; 
                newEmail.StatusId = 0;
                newEmail.FolderId = await MailFolderViewModel.GetFolderId(0, account.Id);
                newEmail.Read = false;

                var listAttach = new List<Attachment>();
                foreach (var attachment in email.Attachments)
                {
                    var newAttach = new Attachment();
                    if (attachment.ContentDisposition != null && attachment.ContentDisposition.Param_FileName != null)
                    {
                        newAttach.Name = attachment.ContentDisposition.Param_FileName;
                    }
                    else
                    {
                        newAttach.Name = "untitled";
                    }

                    newAttach.attach = attachment.Body.Entity.DataToByte();
                    newAttach.ContentTransferEncoding = attachment.ContentTransferEncoding.ToString();
                    newAttach.ContentType = attachment.ContentType.ToString();
                    listAttach.Add(newAttach);
                }
                newEmail.Attachments = listAttach;
                await LetterViewModel.InsertUpdate(newEmail);
            }
            catch (Exception e)
            {
                result = "POP3 server returned: " + e.Message;
            }
            return result;
        }

        public static Task<Letter> Sent(Letter letter, Mail_Message message)
        {
            return Task.Factory.StartNew(() =>
            {
                if (letter.Account.UseSameUserPassSending) SMTP_Client.QuickSendSmartHost("localhost", letter.Account.outServer, letter.Account.outPort,
                    letter.Account.UseSSL, letter.Account.UserName.Trim(), letter.Account.Password.Trim(), message);
                else SMTP_Client.QuickSendSmartHost(letter.Account.outServer, letter.Account.outPort, letter.Account.UseSSL, message);

                letter.MessageId = message.MessageID;
                letter.StatusId = 1;
                letter.DepartureDate = message.Date;
                return letter;               
            });
        }

        public static async Task<string> ClearFolder(int accountId, int folderId)
        {
            return await LetterViewModel.Delete(accountId, folderId); ;
        }

        public static async Task<ObservableCollection<Letter>> Searching(EmailAccount account, int folderId, string searchString)
        {
            return await LetterViewModel.GetList(account, folderId, searchString); ;
        }
    }
}
